<!-- 1、all是一个静态方法，返回的是一个promise实例
2、接收到的是一个数组，如果不是数组抛出异常
3、如果接收到是是一个空数组直接兑现
4、处理全部兑现
  4、1记录结果，用数组的索引来记录，避免返回的顺序和传入的顺序不一致
  4.2判断全部兑现，不能使用数组长度和传入数组长度来判断（因为可能有延迟任务，不清楚是哪个promise先返回），使用累计来判断，当累计的值和传入的数组的长度一致的时候返回
5、处理第一个拒绝 -->
<script>
  function asyncFunc(callback) {
    if (typeof queueMicrotask === 'function') {
      queueMicrotask(callback)
    } else if (typeof MutationObserver === 'function') {
      const observer = new MutationObserver(callback)
      observer.observe(document.body, {
        childList: true,
      })
    } else if (typeof setTimeout === 'function') {
      setTimeout(callback)
    }
  }
      function resolvePromise(promise2, x, resolve, reject) {
        if(promise2===x) {
            return reject(new TypeError('Chaining cycle detected for promise'))
        }
        if(x instanceof MyPromise){
          x.then(res=>console.log(res),res=>reject(res))
        }else{
          resolve(x)
        }
      }
  const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'
  class MyPromise {
    constructor(executor) {
      this.state = PENDING
      this.result = undefined
      this.resolveCallbacks = []
      this.rejectCallbacks = []
      const resolve = (result) => {
        if (this.state === PENDING) {
          this.state = FULFILLED
          this.result = result
          this.resolveCallbacks.forEach((callback) => {
            callback(result)
          })
        }
      }
      const reject = (result) => {
        if (this.state === PENDING) {
          this.state = REJECTED
          this.result = result
          this.rejectCallbacks.forEach((callback) => {
            callback(result)
          })
        }
      }
      try {
        executor(resolve, reject)
      } catch (e) {
        reject(e)
      }
    }

    then(onFulfilled, onRejected) {
      onFulfilled =
        typeof onFulfilled === 'function' ? onFulfilled : (value) => value
      onRejected =
        typeof onRejected === 'function'
          ? onRejected
          : (reason) => {
              throw reason
            }

      const promise2 = new MyPromise((resolve, reject) => {
        if (this.state === FULFILLED) {
          asyncFunc(() => {
            try {
              // 此处的x是第一次return的值
              const x = onFulfilled(this.result)
              resolvePromise(promise2,x,resolve,reject)
            } catch (e) {
              reject(e)
            }
          })
        }
        if (this.state === REJECTED) {
          asyncFunc(() => {
            try {
              const x = onRejected(this.result)
              resolvePromise(promise2,x,resolve,reject)
            } catch (e) {
              reject(e)
            }
          })
        }
        if (this.state === PENDING) {
          this.resolveCallbacks.push(() => {
            asyncFunc(() => {
              try {
                const x = onFulfilled(this.result)
                resolvePromise(promise2,x,resolve,reject)
              } catch (e) {
                reject(e)
              }
            })
          })
          this.rejectCallbacks.push(() => {
            asyncFunc(() => {
              try{
                const x = onRejected(this.result)
                resolvePromise(promise2,x,resolve,reject)
              }catch(e) {
                reject(e)

              }
              
            })
          })
        }
      })

      return promise2
    }
    catch(onRejected){
      return this.then(undefined,onRejected)
    }
    // finally函数的参数会在promise结束时调用,then里面传入同一个函数,return的作用是支持链式编程
    finally(onFinally) {
      return this.then(onFinally,onFinally)
    }
    static resolve(value) {
      if(value instanceof MyPromise) {
        return value
      }
      return new MyPromise((resolve)=>{
        return resolve(value)
      })
    }

    static reject(value) {
      if(value instanceof MyPromise) {
        return value
      }
      return new MyPromise((resolve,reject)=>{
        return reject(value)
      })
    }

    static race(promises) {
      return new MyPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
          return reject(new TypeError('Argument is not iterable'))
        }
        promises.forEach((item)=>{
          // 调用MyPromise.resolve是为了把传入的参数都封装成promise
          MyPromise.resolve(item).then(res=>{
            return resolve(res)
          },err=>{
            return reject(err)
          })
        })
      })
    }

    static all(promises) {
      return new MyPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
          return reject(new TypeError('Argument is not iterable'))
        }
        if(promises.length===0) {
          return resolve([])
        }
        const results = []
        let count = 0
        promises.forEach((p,index)=>{
            MyPromise.resolve(p).then((res)=>{
              results[index] = res
              count++
              promises.length === count && resolve(results)
            },(err)=>{
              reject(err)
            })
        })
      })
    }

  }

const p1 = new MyPromise((resolve,reject)=>{
  setTimeout(()=>{
    resolve('suc')
  },3000)
})

const p2 = new MyPromise((resolve,reject)=>{
  setTimeout(()=>{
    reject('err')
  },2000)
})
const p3=3
MyPromise.all([p1,p2,p3]).then((res)=>{
  console.log('res',res)
},(err)=>{
  console.log('err',err)
})
</script>
